package com.cskaoyan.javase.oop3._1interface._5extends;

import org.omg.CORBA.PUBLIC_MEMBER;

/**
 * 方法传值
 * 方法的形参在方法调用传入实参时，不一定要求数据类型完全一致。
 * 基本类型：对于基本数据类型的方法形参，存在自动类型提升。
 * 引用类型： 对于引用数据类型的方法传参，存在自动向上转型。
 * 形参如果写一个普通类：调用方法时需要传入的是该类的对象或者该类的子类对象
 * 形参如果写一个抽象类：调用方法时需要传入的是该抽象类的子类对象
 * 形参如果写一个接口：调用方法时需要传入的是该接口的子类对象
 *
 * 方法的返回值
 * 方法的返回值类型，和在方法体中返回具体值（对象）时，不一定要求数据类型完全一致。
 * 基本类型：方法体中，返回一个具体的值不要求和返回值类型完全一致，存在自动类型提升。
 * 引用类型： 在方法体中，返回一个对象时不要求就是返回值类型的对象，存在自动向上转型。
 * 返回值类型如果写一个普通类：可以返回该类的对象或者该类的子类对象
 * 返回值类型如果写一个抽象类：返回该抽象类的子类对象。
 * 返回值类型如果写一个接口：返回该接口的子类对象。
 *
 * 方法重写中的返回值,父子类返回值并不要求完全一致
 * 而是:
 *      1.void和基本数据类型的返回值类型,必须是一致的
 *      2.引用数据类型返回值类型时
 *          如果父类方法返回一个父类类型
 *          那么子类重写方法的返回值类型可以是子类类型
 *          (当然也可以保持一致)
 *
 *
 * @since 14:40
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        test(new Father());
        test(new Son());
        // 抽象类作为形参时,实参必须传入它的实现类对象
        test(new BaseFatherSon());

        // 接口作为形参时,实参必须传入它的实现类对象
        test(new A());
    }

    public static Father test() {
        // return new Father();
        return new Son();
    }

    public static void test(Father f) {
    }

    public static void test(BaseFather bf) {
    }

    public static BaseFather test2() {
        // 抽象类作为返回值类型时,必须返回它的实现类对象
        return new BaseFatherSon();
    }

    public static IA test3() {
        // 接口作为返回值类型时,必须返回它的实现类对象
        return new A();
    }

    public static void test(IA ia) {
    }
}

interface IA {
}

class A implements IA {
}

abstract class BaseFather {
}

class BaseFatherSon extends BaseFather {
}

class Father {
    Object test(Object o) {
        return new Object();
    }

    Father test2(){
        return new Son();
    }
}

class Son extends Father {
    @Override
    String test(Object o) {
        return "abc";
    }

    @Override
    Son test2() {
        return new Son();
    }
}